﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common_Code.Math_Extensions
{
    public class Backwards_Difference : Interpolation<double>
    {
        List<double> x;
        List<double> y;
        List<List<double>> rows;
        double h;

        public Backwards_Difference()
        {
            this.x = new List<double>();
            this.y = new List<double>();
            this.rows = new List<List<double>>();
            this.h = 0;
        }

        public Backwards_Difference(double[] x, double[] y)
        {
            if (x.Length != y.Length)
                throw new NotSupportedException("The length's have to be the same");
            this.x = new List<double>();
            this.y = new List<double>();
            this.rows = new List<List<double>>();
            this.h = 0;
            GenTable(x, y);
        }

        public double GetInterpolationAt(double val)
        {
            if (this.x.Count == 0)
                throw new NotSupportedException("The difference table has not been generated yet");
            var ans = y[0] * x[0];
            double mul = 1;
            double fac = 0;
            for (var i = 0; i < rows.Count; i++)
            {
                mul *= (val - x[i]);
                fac *= (i + 1);
                ans += (mul * rows[i][0]) / fac;
            }
            return ans;
        }

        public void AddPoint(double x, double y)
        {
            throw new NotImplementedException();
        }

        private void GenTable(double[] x, double[] y)
        {
            var subList = new List<double>();
            double temp = 0;
            h = x[1] - x[0];
            for (var i = 0; i < x.Length; i++)
            {
                this.x.Add(x[i]);
                this.y.Add(y[i]);
                for (var j = 0; j < (x.Length - i - 1); j++)
                {
                    temp = y[j + 1] - y[j];
                    if (i == 0)
                        h = x[i + 1] - x[i];
                    else if ((x[i + 1] - x[i]) != h)
                        throw new NotSupportedException("The height is not consitent");
                    subList.Add(temp);
                }
                rows.Add(subList);
                subList.Clear();
            }
        }

        public void AddPoints(double[] x, double[] y)
        {
            if (x.Length != y.Length)
                throw new NotSupportedException("The length's have to be the same");
            if (this.x.Count != 0)
            {
                for (var i = 0; i < (x.Length - 1); i++)
                {
                    AddPoint(x[i], y[i]);
                }
            }
            else
                GenTable(x, y);
        }
    }
}
